package com.hong.jarlauncher;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.function.Consumer;


import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLightLaf;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.function.Consumer;

public class ServicePanel extends JPanel {
    private JTextField serviceNameField;
    private JTextField jrePathField;
    private JTextField jarPathField;
    private JTextField jarNameField;
    private JTextField argumentsField;
    private JTextArea commandPreviewArea;
    private JTextArea logArea;
    private JButton startButton;
    private JButton stopButton;
    private JButton restartButton;
    private JButton clearLogButton;
    private JButton toggleThemeButton;

    private Process process;
    private boolean isRunning = false;
    private boolean darkTheme = false;
    private final Consumer<String> onServiceNameChange;

    public ServicePanel(Consumer<String> onServiceNameChange) {
        this.onServiceNameChange = onServiceNameChange;
        setLayout(new BorderLayout());
        setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        JPanel configPanel = createConfigPanel();
        add(configPanel, BorderLayout.NORTH);

        JPanel logPanel = createLogPanel();
        add(logPanel, BorderLayout.CENTER);

        JPanel buttonPanel = createButtonPanel();
        add(buttonPanel, BorderLayout.SOUTH);

        updateCommandPreview();
    }

    private JPanel createConfigPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createTitledBorder("服务配置"));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;

        gbc.gridx = 0;
        gbc.gridy = 0;
        panel.add(new JLabel("服务名称:"), gbc);

        gbc.gridx = 1;
        serviceNameField = new JTextField(20);
        serviceNameField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void update() {
                onServiceNameChange.accept(serviceNameField.getText());
                updateCommandPreview();
            }
        });
        panel.add(serviceNameField, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        panel.add(new JLabel("JRE路径:"), gbc);

        gbc.gridx = 1;
        jrePathField = new JTextField(20);
        jrePathField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void update() {
                updateCommandPreview();
            }
        });
        panel.add(jrePathField, gbc);

        gbc.gridx = 2;
        JButton jreBrowseButton = new JButton("浏览...");
        jreBrowseButton.addActionListener(e -> browseForJre());
        panel.add(jreBrowseButton, gbc);

        gbc.gridx = 0;
        gbc.gridy = 2;
        panel.add(new JLabel("JAR路径:"), gbc);

        gbc.gridx = 1;
        jarPathField = new JTextField(20);
        jarPathField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void update() {
                updateCommandPreview();
            }
        });
        panel.add(jarPathField, gbc);

        gbc.gridx = 2;
        JButton jarBrowseButton = new JButton("浏览...");
        jarBrowseButton.addActionListener(e -> browseForJar());
        panel.add(jarBrowseButton, gbc);

        gbc.gridx = 0;
        gbc.gridy = 3;
        panel.add(new JLabel("JAR名称:"), gbc);

        gbc.gridx = 1;
        jarNameField = new JTextField(20);
        jarNameField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void update() {
                updateCommandPreview();
            }
        });
        panel.add(jarNameField, gbc);

        gbc.gridx = 0;
        gbc.gridy = 4;
        panel.add(new JLabel("启动参数:"), gbc);

        gbc.gridx = 1;
        argumentsField = new JTextField(20);
        argumentsField.setToolTipText("例如: --spring.profiles.active=dev");
        argumentsField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void update() {
                updateCommandPreview();
            }
        });
        panel.add(argumentsField, gbc);

        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.gridwidth = 3;
        panel.add(new JLabel("命令预览:"), gbc);

        gbc.gridy = 6;
        commandPreviewArea = new JTextArea(3, 50);
        commandPreviewArea.setEditable(false);
        commandPreviewArea.setBackground(getBackground());
        JScrollPane scrollPane = new JScrollPane(commandPreviewArea);
        panel.add(scrollPane, gbc);

        return panel;
    }

    private JPanel createLogPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createTitledBorder("日志输出"));

        logArea = new JTextArea(10, 60);
        logArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(logArea);

        panel.add(scrollPane, BorderLayout.CENTER);

        return panel;
    }

    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));

        clearLogButton = new JButton("清空日志");
        clearLogButton.setMnemonic(KeyEvent.VK_C);
        clearLogButton.addActionListener(e -> clearLog());
        panel.add(clearLogButton);

        toggleThemeButton = new JButton("暗色主题");
        toggleThemeButton.setMnemonic(KeyEvent.VK_T);
        toggleThemeButton.addActionListener(e -> toggleTheme());
        panel.add(toggleThemeButton);

        startButton = new JButton("启动");
        startButton.setMnemonic(KeyEvent.VK_S);
        startButton.addActionListener(e -> startService());
        panel.add(startButton);

        stopButton = new JButton("停止");
        stopButton.setMnemonic(KeyEvent.VK_T);
        stopButton.addActionListener(e -> stopService());
        stopButton.setEnabled(false);
        panel.add(stopButton);

        restartButton = new JButton("重启");
        restartButton.setMnemonic(KeyEvent.VK_R);
        restartButton.addActionListener(e -> restartService());
        restartButton.setEnabled(false);
        panel.add(restartButton);

        return panel;
    }

    private abstract class DocumentAdapter implements DocumentListener {
        @Override
        public void changedUpdate(DocumentEvent e) { update(); }
        @Override
        public void insertUpdate(DocumentEvent e) { update(); }
        @Override
        public void removeUpdate(DocumentEvent e) { update(); }

        protected abstract void update();
    }

    private void browseForJre() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnVal = chooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            jrePathField.setText(chooser.getSelectedFile().getAbsolutePath());
        }
    }

    private void browseForJar() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toLowerCase().endsWith(".jar");
            }

            public String getDescription() {
                return "JAR 文件 (*.jar)";
            }
        });

        int returnVal = chooser.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File selectedFile = chooser.getSelectedFile();
            jarPathField.setText(selectedFile.getParent());
            jarNameField.setText(selectedFile.getName());
        }
    }

    private void updateCommandPreview() {
        String jrePath = jrePathField.getText().trim();
        String jarPath = jarPathField.getText().trim();
        String jarName = jarNameField.getText().trim();
        String arguments = argumentsField.getText().trim();

        StringBuilder command = new StringBuilder();

        if (!jrePath.isEmpty()) {
            command.append(jrePath).append(File.separator).append("bin").append(File.separator).append("java");
        } else {
            command.append("java");
        }

        command.append(" -jar ");

        if (!jarPath.isEmpty()) {
            command.append(jarPath).append(File.separator);
        }

        command.append(jarName);

        if (!arguments.isEmpty()) {
            command.append(" ").append(arguments);
        }

        commandPreviewArea.setText(command.toString());
    }

    public void startService() {
        clearLog();
        if (isRunning) {
            log("服务已经在运行中");
            return;
        }

        String command = commandPreviewArea.getText();
        if (command.isEmpty() || command.equals("java -jar")) {
            log("请先配置服务参数");
            return;
        }

        try {
            log("启动服务: " + command);
            process = Runtime.getRuntime().exec(command);

            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        log(line);
                    }
                } catch (IOException e) {
                    log("读取输出流错误: " + e.getMessage());
                }
            }).start();

            new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        log(line);
                    }
                } catch (IOException e) {
                    log("读取错误流错误: " + e.getMessage());
                }
            }).start();

            isRunning = true;
            updateButtonStates();

            new Thread(() -> {
                try {
                    int exitCode = process.waitFor();
                    isRunning = false;
                    SwingUtilities.invokeLater(() -> {
                        log("服务已停止，退出码: " + exitCode);
                        updateButtonStates();
                    });
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }).start();

        } catch (IOException e) {
            log("启动服务失败: " + e.getMessage());
        }
    }

    public void stopService() {
        if (!isRunning || process == null) {
            log("服务未运行");
            return;
        }

        log("停止服务...");
        process.destroy();
    }

    public void restartService() {
        clearLog();
        stopService();

        new Thread(() -> {
            try {
                Thread.sleep(1000);
                SwingUtilities.invokeLater(this::startService);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }

    private void clearLog() {
        logArea.setText("");
    }

    private void toggleTheme() {
        darkTheme = !darkTheme;
        updateTheme();
    }

    private void updateTheme() {
        try {
            if (darkTheme) {
                UIManager.setLookAndFeel(new FlatDarkLaf());
                toggleThemeButton.setText("亮色主题");
            } else {
                UIManager.setLookAndFeel(new FlatLightLaf());
                toggleThemeButton.setText("暗色主题");
            }
            SwingUtilities.updateComponentTreeUI(this);
        } catch (UnsupportedLookAndFeelException e) {
            log("切换主题失败: " + e.getMessage());
        }
    }

    private void updateButtonStates() {
        startButton.setEnabled(!isRunning);
        stopButton.setEnabled(isRunning);
        restartButton.setEnabled(isRunning);
    }

    private void log(String message) {
        SwingUtilities.invokeLater(() -> {
            logArea.append(message + "\n");
            logArea.setCaretPosition(logArea.getDocument().getLength());
        });
    }
}